package team.nmsg.ge.system.init.websocket;

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import team.nmsg.ge.system.bean.AppToken;
import team.nmsg.ge.system.controller.CommonController;

@Aspect
@Component
@ServerEndpoint(value = "/websocket/{id}")
public class SysMsgPusher {
	private static Logger logger = LoggerFactory.getLogger(CommonController.class);
	
	private static SysMsgPusher webSocketServer = null;

	public static SysMsgPusher getMsgPusher(){
		if(webSocketServer == null){
			webSocketServer = new SysMsgPusher();
		}
		return webSocketServer;
	}

	private static int onlineCount = 0;
	private static ConcurrentHashMap<String, SysMsgPusher> webSocketSet = new ConcurrentHashMap<>();

	//与某个客户端的连接会话，需要通过它来给客户端发送数据
	private Session session;
	
	private String id = "";
	/**
	 * 连接建立成功调用的方法*/
	@OnOpen
	public void onOpen(@PathParam(value = "id") String id, Session session) {
		this.session = session;
		this.id = id;//接收到发送消息的人员编号
		webSocketSet.put(id, this);     //加入set中
		addOnlineCount();           //在线数加1
		try {
			sendMessage("连接成功");
		} catch (IOException e) {
			logger.error("websocket IO异常");
		}
	}

	/**
	 * 连接关闭调用的方法
	 */
	@OnClose
	public void onClose() {
		webSocketSet.remove(this.id);  //从set中删除
		subOnlineCount();           //在线数减1
		logger.info("有一连接关闭！当前在线人数为" + getOnlineCount());
	}

	/**
	 *
	 * @param session
	 * @param error
	 */
	@OnError
	public void onError(Session session, Throwable error) {
		logger.error("发生错误");
		error.printStackTrace();
	}


	private synchronized void sendMessage(String message) throws IOException {
		this.session.getBasicRemote().sendText(message);
	}

	/**
	 * 发送信息给指定ID用户，如果用户不在线则返回不在线信息给自己
	 * @param message
	 * @param sendUserId clientToken
	 * @throws IOException
	 */
	public void sendtoUser(String message,String sendUserId) throws IOException {
		if (webSocketSet.get(sendUserId) != null) {
				webSocketSet.get(sendUserId).sendMessage(message);
		} else {
			logger.info("offline");
		}
	}

	/**
	 * 发送信息给所有人
	 * @param message
	 * @throws IOException
	 */
	public void sendtoAll(String message) throws IOException {
		for (String key : webSocketSet.keySet()) {
			try {
				webSocketSet.get(key).sendMessage(message);
				logger.info("send success");
			} catch (Exception e) {
				logger.error("" ,e.getMessage() );
			}
		}
	}


	public static synchronized int getOnlineCount() {
		return onlineCount;
	}

	public static synchronized void addOnlineCount() {
		SysMsgPusher.onlineCount++;
	}

	public static synchronized void subOnlineCount() {
		SysMsgPusher.onlineCount--;
	}
	
	
	@Pointcut("execution ( * team.nmsg.ge.system.service.ICacheService.removeTokenFromCahce(..)) ")  
	public void removeSoceket(){} 
	
	@AfterReturning(value="removeSoceket()", returning="rtv")
	public void removeSoceketCall(JoinPoint joinPoint, Object rtv) {

		try {
			Object[] args = joinPoint.getArgs();
			AppToken tokenObj = (AppToken)args[0];
			String clientToken = tokenObj.createClientToken();
			if(webSocketSet.containsKey(clientToken)){
				webSocketSet.remove(clientToken);
			}

		} catch( Exception e) {
			logger.error(e.getMessage());
		}

	 }
}
